package com.nk.system.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.Security;
import java.security.spec.InvalidParameterSpecException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.log4j.Logger;

import sun.misc.BASE64Encoder;

public class CommonHelper {

	public static final Locale LOCALE = Locale.US;

	public static final String DATE_PATTERN = "dd/MM/yyyy";
	public static final String DATE_PATTERN_UI = "yyyy-MM-dd";
	public static final String DATE_PATTERN_SB = "yyMMdd";
	public static final String DATETIME_PATTERN = "dd/MM/yyyy HH:mm:ss";
	public static final String TIME_PATTERN_ARC = "HHmmss";
	public static final String MOBILE_NO_PATTERN = "[0][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]";
	public static final String DIGITS_PATTERN = "\\d+";
	public static final String THAI_CHARSET = "TIS-620";
	
	public static final long MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;

	public static final SimpleDateFormat dateFormatter = new SimpleDateFormat(DATE_PATTERN, LOCALE);

	public static final SimpleDateFormat dateFormatterUI = new SimpleDateFormat(DATE_PATTERN_UI, LOCALE);

	public static final SimpleDateFormat dateFormatterSB = new SimpleDateFormat(DATE_PATTERN_SB, LOCALE);

	private static final Logger log = Logger.getLogger(CommonHelper.class);
	
	public static final String getNumber(long num, int fraction) {
		
		NumberFormat format = NumberFormat.getInstance();
		format.setGroupingUsed(true);
		format.setMaximumFractionDigits(fraction);
		format.setMinimumFractionDigits(fraction);
		return format.format(num);
	}
	
	public static final String getNumber(double num, int fraction) {
		
		NumberFormat format = NumberFormat.getInstance();
		format.setGroupingUsed(true);
		format.setMaximumFractionDigits(fraction);
		format.setMinimumFractionDigits(fraction);
		return format.format(num);
	}

	/**
	 * Prefix the number with '0' to match the specified length
	 * 
	 * @param number
	 * @param length
	 * @return
	 */
	public static final String fillZeroPrefix(long number, int length) {

		String result = "" + number;
		int zeroToAdd = length - result.length();

		for (int i = 0; i < zeroToAdd; i++) {
			result = "0" + result;
		}

		return result;
	}

	public static final String objectsToString(Object[] objects) {

		if (objects == null) {
			return null;
		} else {
			String result = objects.length + " [";
			for (Object object : objects) {
				result = result + object + ",";
			}
			result = result + "]";

			return result;
		}
	}

	public static final String getDateTodayDefault() {

		return getDateString(null, null);
	}

	public static synchronized final String getDateTimeDefaultFormat(Date date) {
		SimpleDateFormat dateFormat = new SimpleDateFormat(DATETIME_PATTERN, LOCALE);
		return dateFormat.format(date);
	}

	public static final long calDifDayWithToday(Date date) {
		long difMilliSec = date.getTime() - currentDateZeroTime().getTime().getTime();
		long difDay = difMilliSec / MILLISECONDS_PER_DAY;
		return difDay;
	}

	public static final double convertString2Double(String amount, int scale) {
		try {
			String limit = amount;
			String strDecimal = limit.substring(limit.length() - scale, limit.length());
			String strInteger = limit.substring(0, limit.length() - scale);
			String strlimit = strInteger + "." + strDecimal;
			return Double.parseDouble(strlimit);
		} catch (Exception e) {
			throw new RuntimeException("Cann't convert String to double " + e.getMessage());
		}
	}

	public static synchronized final String getDateString(String pattern, Calendar cal) {

		SimpleDateFormat dateFormatterTmp = null;
		if (pattern == null) {
			pattern = DATE_PATTERN_UI; // defailt pattern
		}
		dateFormatterTmp = new SimpleDateFormat(pattern, LOCALE);

		if (cal == null) {
			cal = currentDateTime();
		}

		return dateFormatterTmp.format(cal.getTime());
	}

	public static final String parseCronDaily(String hhmm) {

		if (hhmm == null || hhmm.trim().length() != 4) {
			throw new RuntimeException("parseCron hhmm INVALID : " + hhmm);
		}

		hhmm = hhmm.trim();

		// cron sample 0 20 17 * * ?
		int h = Integer.parseInt(hhmm.substring(0, 2));
		int m = Integer.parseInt(hhmm.substring(2));

		if (h < 0 || h > 23)
			throw new RuntimeException("invalid hour : " + h);
		if (m < 0 || m > 59)
			throw new RuntimeException("invalid minute : " + m);

		String cron = "0 " + m + " " + h + " * * ?";
		log.info("Cron parsed as " + cron + " [" + hhmm + "]");
		return cron;
	}

	/**
	 * Create a date object with specified hour and minute
	 * 
	 * @param hhmm
	 * @return
	 */
	public static final Date parseTime(String hhmm) {

		if (hhmm == null || hhmm.trim().length() != 4) {
			throw new RuntimeException("hhmm INVALID : " + hhmm);
		}

		hhmm = hhmm.trim();

		Calendar calNow = Calendar.getInstance(Locale.US);
		calNow.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hhmm.substring(0, 2)));
		calNow.set(Calendar.MINUTE, Integer.parseInt(hhmm.substring(2)));
		calNow.set(Calendar.SECOND, 0);
		calNow.set(Calendar.MILLISECOND, 0);

		return calNow.getTime();
	}

	public static final Date parseTimeTomorrow(String hhmm) {
		Calendar calNow = Calendar.getInstance(Locale.US);
		calNow.setTime(parseTime(hhmm));
		calNow.set(Calendar.DATE, calNow.get(Calendar.DATE)+1);
		return calNow.getTime();
	}
	
	public static final void resetBeginOfDayTime(Calendar cal) {

		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
	}

	public static final void resetEndOfDayTime(Calendar cal) {

		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		cal.set(Calendar.MILLISECOND, 999);
	}

	public static final Calendar currentDateZeroTime() {

		Calendar calNow = Calendar.getInstance(Locale.US);
		calNow.set(Calendar.HOUR_OF_DAY, 0);
		calNow.set(Calendar.MINUTE, 0);
		calNow.set(Calendar.SECOND, 0);
		calNow.set(Calendar.MILLISECOND, 0);

		return calNow;
	}

	public static final Calendar currentDateTime() {

		Calendar calNow = Calendar.getInstance(Locale.US);

		return calNow;
	}

	public static synchronized final Calendar parseCalendar(String dateString) {

		if (dateString == null || dateString.trim().equals("")) {
			throw new RuntimeException("invalid date input " + dateString);
		}

		Date dTmp = null;
		try {
			dTmp = CommonHelper.dateFormatter.parse(dateString.trim());
		} catch (ParseException e) {
			log.error("Error parsing dateInput : " + dateString.trim(), e);
			throw new RuntimeException("Error parsing dateInput : " + dateString.trim(), e);
		}

		Calendar calNow = Calendar.getInstance(Locale.US);
		calNow.setTime(dTmp);

		calNow.set(Calendar.HOUR_OF_DAY, 0);
		calNow.set(Calendar.MINUTE, 0);
		calNow.set(Calendar.SECOND, 0);
		calNow.set(Calendar.MILLISECOND, 0);

		return calNow;
	}
	
	public static synchronized final Calendar parseCalendar(String dateTimeString, String pattern) {

		if (dateTimeString == null || dateTimeString.trim().equals("")) {
			throw new RuntimeException("invalid date input " + dateTimeString);
		}

		Date dTmp = null;
		try {
			SimpleDateFormat dateFormatterUITmp = new SimpleDateFormat(pattern, LOCALE);
			dTmp = dateFormatterUITmp.parse(dateTimeString.trim());
		} catch (ParseException e) {
			log.error("Error parsing dateInput : " + dateTimeString.trim(), e);
			throw new RuntimeException("Error parsing dateInput : " + dateTimeString.trim(), e);
		}

		Calendar calNow = Calendar.getInstance(Locale.US);
		calNow.setTime(dTmp);

//		calNow.set(Calendar.HOUR_OF_DAY, 0);
//		calNow.set(Calendar.MINUTE, 0);
//		calNow.set(Calendar.SECOND, 0);
//		calNow.set(Calendar.MILLISECOND, 0);

		return calNow;
	}

	public static synchronized final Date parseDateEndOfDay(String dateString) {

		if (dateString == null || dateString.trim().equals("")) {
			throw new RuntimeException("invalid date input " + dateString);

		}

		try {
			Date tmpDate = dateFormatter.parse(dateString.trim());
			Calendar tmpCal = CommonHelper.currentDateTime();
			tmpCal.setTime(tmpDate);
			CommonHelper.resetEndOfDayTime(tmpCal);
			return tmpCal.getTime();

		} catch (ParseException e) {
			log.error("Error parsing dateInput : " + dateString.trim(), e);
			throw new RuntimeException("Error parsing dateInput : " + dateString.trim(), e);
		}
	}

	public static synchronized final Date parseDateSB(String dateString) {

		if (dateString == null || dateString.trim().equals("")) {
			return null;
		}

		try {
			return dateFormatterSB.parse(dateString.trim());
		} catch (ParseException e) {
			log.error("Error parsing dateInput SB : " + dateString.trim(), e);
			return null;
		}
	}

	public static synchronized final Date parseDate(String dateTimeString, String pattern) {

		if (dateTimeString == null || dateTimeString.trim().equals("")) {
			throw new RuntimeException("invalid date input " + dateTimeString);
		}

		try {
			SimpleDateFormat dateFormatterUITmp = new SimpleDateFormat(pattern, LOCALE);
			return dateFormatterUITmp.parse(dateTimeString.trim());
		} catch (ParseException e) {
			log.error("Error parsing dateInput : " + dateTimeString.trim(), e);
			throw new RuntimeException("Error parsing dateInput : " + dateTimeString.trim(), e);
		}
	}

	public static synchronized final Date parseDate(String dateString) {

		if (dateString == null || dateString.trim().equals("")) {
			throw new RuntimeException("invalid date input " + dateString);
		}

		try {
			return dateFormatterUI.parse(dateString.trim());
		} catch (ParseException e) {
			log.error("Error parsing dateInput : " + dateString.trim(), e);
			throw new RuntimeException("Error parsing dateInput : " + dateString.trim(), e);
		}
	}

	public static synchronized final byte[] unZip(byte[] contents) throws Exception {
		ByteArrayOutputStream bos = null;
		BufferedOutputStream dest = null;
		ZipInputStream zis = null;
		ZipEntry entry = null;
		try {
			int BUFFER = 4 * 1024;

			bos = new ByteArrayOutputStream();
			dest = new BufferedOutputStream(bos, BUFFER);
			zis = new ZipInputStream(new BufferedInputStream(new ByteArrayInputStream(contents)));

			int i = 0;
			while ((entry = zis.getNextEntry()) != null) {
				System.out.println("Extracting: " + entry);

				if (i > 0 && entry != null) {
					throw new Exception("Entry of zipfile is more than 1");
				}

				int count;
				byte data[] = new byte[BUFFER];

				while ((count = zis.read(data, 0, BUFFER)) != -1) {
					dest.write(data, 0, count);
				}
				i++;
			}

			dest.flush();
			dest.close();

			zis.close();
			return bos.toByteArray();

		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new Exception(e);
		} finally {
			zis = null;
			dest = null;
			bos = null;
			entry = null;
		}

	}

	public static synchronized byte[] getBytesFromFile(File file) throws Exception {
		log.info("reading file "+file.getName());

		/** Get and validate the size of the file */
		long length = file.length();
		log.info(" > read file length: " + length);
		if (length > Integer.MAX_VALUE) {
			throw new RuntimeException("File size ("+length+") is over max size ("+Integer.MAX_VALUE+")");
		}

		/** Create the byte array to hold the data */
		byte[] bytesArr = new byte[(int) length];
		FileInputStream fs = null;
		BufferedInputStream inputStream = null;
		try {
			fs = new FileInputStream(file);
			inputStream = new BufferedInputStream(fs);
	
			/** Read in the bytes */
			int offset = 0;
			int numRead = 0;
			while (offset < bytesArr.length && (numRead = inputStream.read(bytesArr, offset, bytesArr.length - offset)) >= 0) {
				offset += numRead;
			}
	
			/** Ensure all the bytes have been read in */
			if (offset < bytesArr.length) {
				throw new IOException("Could not completely read file");
			}
	
		}catch(Exception e){
			log.error(e, e);
		}finally{
			try {
				if(inputStream != null){
					inputStream.close();
				}
				if(fs != null){
					fs.close();
				}
			} catch (IOException e) {
				log.error(e, e);
				throw new Exception(e);
			}
		}
		return bytesArr;
	}

	/**
	 * Check digit of account number KBank only
	 * 
	 * @param accNumber10digit
	 * @return true or false
	 * @throws Exception
	 */
	public static boolean checkDigitAccKBank(String accNumber10digit) throws Exception {
		if (accNumber10digit != null && !"".equals(accNumber10digit) && accNumber10digit.length() == 10) {
			try {
				// 4 3 2 7 6 5 4 3 2 1
				int acc1 = Integer.parseInt(accNumber10digit.substring(0, 1)) * 4;
				int acc2 = Integer.parseInt(accNumber10digit.substring(1, 2)) * 3;
				int acc3 = Integer.parseInt(accNumber10digit.substring(2, 3)) * 2;
				int acc4 = Integer.parseInt(accNumber10digit.substring(3, 4)) * 7;
				int acc5 = Integer.parseInt(accNumber10digit.substring(4, 5)) * 6;
				int acc6 = Integer.parseInt(accNumber10digit.substring(5, 6)) * 5;
				int acc7 = Integer.parseInt(accNumber10digit.substring(6, 7)) * 4;
				int acc8 = Integer.parseInt(accNumber10digit.substring(7, 8)) * 3;
				int acc9 = Integer.parseInt(accNumber10digit.substring(8, 9)) * 2;
				int acc10 = Integer.parseInt(accNumber10digit.substring(9, 10)) * 1;

				int sum_acc = acc1 + acc2 + acc3 + acc4 + acc5 + acc6 + acc7 + acc8 + acc9 + acc10;
				int result_check_acc = sum_acc % 11;

				if (result_check_acc == 0 || result_check_acc == 2) {
					return true;
				}
			} catch (Exception e) {
				log.error(e.getMessage(), e);
				throw new Exception(e);
			}
		}

		return false;
	}
	
	public static boolean isValidCitizenID(String citizenID){
		boolean result = false;
		try{
		    if(citizenID == null || citizenID.length() != 13){
		    	return false;
		    }
		    int sum = 0;
		    for(int i=0; i < 12; i++){
		    	sum += Character.digit(citizenID.charAt(i), 10)*(13-i);
		    }
		    if((11-sum%11)%10 != Character.digit(citizenID.charAt(12), 10)){
		    	return false;
		    }
		    result = true;
		}catch(Exception e){
			log.error(e, e);
		}
	    return result;
	}
	
	/** check 4th digit of accountNo: 1=current, 2=saving */
	public static boolean isCurrentOrSavingAccount(String accNumber10digit) throws Exception{
		char c = accNumber10digit.charAt(3);
		return c == '1' || c == '2';
	}
	
	

	public static final Calendar startOfTomorrow() {
		Calendar calTomorrow = Calendar.getInstance(Locale.US);
		calTomorrow.set(Calendar.DATE, calTomorrow.get(Calendar.DATE)+1);
		calTomorrow.set(Calendar.HOUR_OF_DAY, 0);
		calTomorrow.set(Calendar.MINUTE, 0);
		calTomorrow.set(Calendar.SECOND, 0);
		calTomorrow.set(Calendar.MILLISECOND, 0);
		return calTomorrow;
	}
	
	public static boolean isUTF16File(String fullFileName){
		boolean result = false;
		FileInputStream is = null;
		try{
			File file = new File(fullFileName);
			is = new FileInputStream(file);
			byte[] buf = new byte[(int) file.length()];
			int bytesRead;
			
			if ((bytesRead = is.read(buf)) != -1) {
			
				if (buf[0] == -1 && buf[1] == -2) {
					result = true;
				}
			}
		}catch(Exception e){
			log.error(e,e);
		}finally{
			try{
				is.close();
			}catch(Exception e2){
				log.error(e2,e2);
			}
		}
		return result;
	}
	
	public static boolean isUTF8File(String fullFileName){
		boolean result = false;
		FileInputStream is = null;
		try{
			File file = new File(fullFileName);
			is = new FileInputStream(file);
			byte[] buf = new byte[(int) file.length()];
			int bytesRead;
			
			if ((bytesRead = is.read(buf)) != -1) {
			
				if (buf[0] == -17 && buf[1] == -69 && buf[2] == -65) {
					result = true;
				}
			}
		}catch(Exception e){
			log.error(e,e);
		}finally{
			try{
				is.close();
			}catch(Exception e2){
				log.error(e2,e2);
			}
		}
		return result;
	}
	
	/** check if private address
	10.0.0.0        -   10.255.255.255  (10/8 prefix)
    172.16.0.0      -   172.31.255.255  (172.16/12 prefix)
    192.168.0.0     -   192.168.255.255 (192.168/16 prefix)
    */
	public static boolean isPrivateIP(String ipAddr){
		try{
			String[] idAddrArr = ipAddr.split("\\.");
			int firstAddr = -1;
			int secondAddr = -1;
			if(idAddrArr.length == 4){
				firstAddr = Integer.parseInt(idAddrArr[0]);
				secondAddr = Integer.parseInt(idAddrArr[1]);
			}
			boolean result = ipAddr.equals("127.0.0.1") || ipAddr.equals("localhost")
				|| firstAddr == 10
				|| (firstAddr == 172 && secondAddr >= 16 && secondAddr <= 31)
				|| (firstAddr == 192 && secondAddr == 168);
			log.info("isPrivateIP of "+ipAddr+" = "+result);
			return result;
		}catch(Exception e){
			log.error(e, e);
		}
		return false;
	}
	
	public static boolean isToday(Date date){
		Calendar dateCal = Calendar.getInstance(Locale.US);
		dateCal.setTime(date);
		resetBeginOfDayTime(dateCal);
		Calendar todayCal = currentDateZeroTime();
		return dateCal.equals(todayCal);
	}
	
	public static void callCFIScript(String cfiPath) throws Exception {
		final String CFI_TRANS_NUM_OUT_FIELD_NAME = "LocalTransactionNumber";

		try {
			log.info("Calling... CFI SCript " + cfiPath);
			Process proc = Runtime.getRuntime().exec(new String[] { cfiPath });
			log.info("Aleady Called CFI SCript");

			String line;
			BufferedReader input = new BufferedReader(new InputStreamReader(proc.getInputStream()));
			while ((line = input.readLine()) != null) {
				log.info("stdin : " + line);
			}
			input.close();
			
			List<String> cfiLocalTransNumList = new ArrayList<String>();
			String lineError = null;
			BufferedReader inputError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
			while ((lineError = inputError.readLine()) != null) {
				log.info("stderrs : " + lineError);
				int transNumFieldPos = lineError.indexOf(CFI_TRANS_NUM_OUT_FIELD_NAME);
				if(transNumFieldPos > -1){
					int startPos = transNumFieldPos + CFI_TRANS_NUM_OUT_FIELD_NAME.length() + 4;
					String cfiLocalTransNum = lineError.substring(startPos);
					cfiLocalTransNumList.add(cfiLocalTransNum);
					log.info(CFI_TRANS_NUM_OUT_FIELD_NAME+"="+cfiLocalTransNum);
				}
			}
			inputError.close();

			int exitValue;
			try {
				log.info("waiting for cfi");
				exitValue = proc.waitFor();
				log.info("exitValue : " + exitValue);
			} catch (InterruptedException e) {
				log.error("Error waiting cfi process : " + e);
			}

			proc.destroy();
			log.info("sub process killed : " + proc);
			proc = null;
						
			/** read result from CFI log */
			chkCFITransfer(cfiLocalTransNumList);
		} catch (Exception e) {
			log.error(e, e);
			throw new RuntimeException(e);
		}
		return;
	}
	
	private static String getCfiLogValue(String line, String key){
		int keyStartPos = line.indexOf(key);
		if(keyStartPos == -1){
			return null;
		}
		int startPos = keyStartPos + key.length() + 1;
		int endPos = line.indexOf(',', startPos);
		return line.substring(startPos, endPos);
	}
	
	public static void chkCFITransfer(List<String> cfiLocalTransNumList) throws Exception {
		final String CFI_TRANS_NUM_LOG_FIELD_NAME = "LocalTranNumber";
		final String CFI_TRANSFER_STATUS_LOG_FIELD_NAME = "TransferStatus";
		final String CFI_STATUS_MSG_LOG_FIELD_NAME = "StatusMsg";
		final String CFI_TRANSFER_STATUS_SUCCESS = "Success";
		final String CFI_LOG_FILE_PATH = "/CyberFusion/log";
		
		/** check cfiLocalTransNumList */
		if(cfiLocalTransNumList.size() == 0){
			throw new Exception("not found any CFI LocalTransactionNumber from error stream");
		}
		
		String currDate = CommonHelper.getDateString("yyyyMMdd", null);
		String cfiLogFullFilePath = CFI_LOG_FILE_PATH + File.separator + "Log.txt." + currDate;
		BufferedReader br = new BufferedReader(new FileReader(cfiLogFullFilePath));
		String logLine = null;
		boolean found = false;
		while ((logLine = br.readLine()) != null) {
			String cfiLocalTransNumInLogFile = getCfiLogValue(logLine, CFI_TRANS_NUM_LOG_FIELD_NAME);
			if(cfiLocalTransNumList.contains(cfiLocalTransNumInLogFile)){
				String transferStatus = getCfiLogValue(logLine, CFI_TRANSFER_STATUS_LOG_FIELD_NAME);
				log.info("check CFI log file: "+cfiLogFullFilePath+"; LocalTranNumber="+cfiLocalTransNumInLogFile+"; transferStatus is "+transferStatus);
				if(!CFI_TRANSFER_STATUS_SUCCESS.equals(transferStatus)){
					String StatusMsg = getCfiLogValue(logLine, CFI_STATUS_MSG_LOG_FIELD_NAME);
					throw new Exception("CFI failed: "+StatusMsg);
				}
				found = true;
				break;
			}
		}
		if(!found){
			throw new Exception("not found LocalTransNum in CFI log");
		}
		return;
	}
	
	public static void listCryptoProviders(){
		Provider [] providers = Security.getProviders();
		for(int i=0; i<providers.length; i++){
			log.info(providers[i]);
		}
	}
    
    public static boolean isMobileNoValid(String mobilePhone){
    	return mobilePhone.matches(MOBILE_NO_PATTERN);
    }
    
    public static boolean isDigits(String digits){
    	return digits.matches(DIGITS_PATTERN);
    }
    
    public static String getSHA1CheckSumFromFile(String filePath){
    	String result = null;
    	FileInputStream fis = null;
    	try{
    		fis = new FileInputStream(filePath);
    		result = getSHA1CheckSum(fis);
    	}catch(Exception e){
    		log.error(e, e);
    	}finally{
    		try{
    			fis.close();
    		}catch(Exception e2){
    			log.error(e2, e2);
    		}
    	}
    	return result;
    }
    
    public static String getSHA1CheckSumFromByteArray(byte[] byteArr){
    	String result = null;
    	ByteArrayInputStream bis = null;
    	try{
    		bis = new ByteArrayInputStream(byteArr);
    		result = getSHA1CheckSum(bis);
    	}catch(Exception e){
    		log.error(e, e);
    	}finally{
    		try{
    			bis.close();
    		}catch(Exception e2){
    			log.error(e2, e2);
    		}
    	}
    	return result;		
    }
    
    public static String getSHA1CheckSum(InputStream is){
    	String result = null;
    	try{
	        MessageDigest md = MessageDigest.getInstance("SHA1");
	        byte[] dataBytes = new byte[1024];	     
	        int nread = 0;	     
	        while ((nread = is.read(dataBytes)) != -1) {
	          md.update(dataBytes, 0, nread);
	        }
	        byte[] mdbytes = md.digest();
	        
	        //convert the byte to hex format
	        StringBuffer sb = new StringBuffer("");
	        for (int i = 0; i < mdbytes.length; i++) {
	        	sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
	        }
	        result = sb.toString();
    	}catch(Exception e){
    		log.error(e, e);
    	}
    	return result;
    }
    
    public static List<String> readFile(String pathFile) {

    	File file = new File(pathFile);
    	FileInputStream fis = null;
    	InputStreamReader isr = null;
    	BufferedReader br = null;
    	List<String> strList = new ArrayList<String>();
    	try{
    		fis = new FileInputStream(file);
    		isr = new InputStreamReader(fis,"TIS-620");	    	  
    		br = new BufferedReader(isr);
    		String strLine;
    		while ((strLine = br.readLine()) != null){
    			strList.add(strLine);
	        }
	    }catch(Exception e){
	    	log.error(e, e);
	    }finally{
	    	try{
		    	if(br != null)br.close();
		    	if(isr != null)isr.close();
		    	if(fis != null)fis.close();
		    	log.info("file "+pathFile+" closed");
	    	}catch(Exception e2){
	    		log.error(e2, e2);
	    	}
	    }
	    return strList;
	}
	
	public static boolean backupFile(String sourceFilePath, String backupPath){

		/** check backup path */
		File backupPathFile = new File(backupPath);
		if(!backupPathFile.exists() && !backupPathFile.mkdir()){
			log.error("backup path is not exist and cannot be created : "+backupPath);
			return false;
		}
		
		/** check source file path */
		File sourceFile = new File(sourceFilePath);
		if(!sourceFile.exists()){
			log.error("Not found source file : "+sourceFilePath);
			return false;
		}
		
		/** get target file path */
		String suffix = CommonHelper.getDateString("_yyyyMMdd_HHmmss",null);			
		String sourceFileName = sourceFilePath.substring(sourceFilePath.lastIndexOf(File.separator)+1);
		String targetFilePath = backupPath+File.separator + sourceFileName + suffix;
		log.info("targetFilePath :"+targetFilePath);
		
		/** check target file path */
		File targetFile = new File(targetFilePath);
		if(targetFile.exists()){
			log.error("target backup file already exist : "+targetFilePath);
			return false;
		}
		
		return sourceFile.renameTo(targetFile);
	}
	
	public static boolean isAddressValid(String address){
        boolean isAddressValid = true;
        StringTokenizer addressTok = new StringTokenizer(address,"\n\r");
        int i = 1;
        while (addressTok.hasMoreTokens()) {
            String object = addressTok.nextToken();
            if ( object.length() > 35 || i > 3 || (i == 3 && object.length() > 29)) {
                isAddressValid = false;
                break;
            }
            i++;
        }
        return isAddressValid;
	}
	
	public static String replaceNewLineWithSpace(String input){
		return input.replaceAll("\\r\\n", " ").replaceAll("\\n", " ");
	}

	public static void writeLine(FileOutputStream fOut, String str){
		try{
			fOut.write(str.getBytes(THAI_CHARSET));
			fOut.write("\r\n".getBytes());
		}catch(IOException e){
			log.error(e, e);
			throw new RuntimeException(e);
		}
	}

	public static String convertUnicode(String str){
		StringBuffer ostr = new StringBuffer();		 
		for(int i=0; i<str.length(); i++){
			char ch = str.charAt(i);
			 
			if ((ch >= 0x0020) && (ch <= 0x007e)){ // Does the char need to be converted to unicode?
				ostr.append(ch); // No.
			} else {// Yes.
				ostr.append("\\u") ; // standard unicode format.
				String hex = Integer.toHexString(str.charAt(i) & 0xFFFF); // Get hex value of the char.
				for(int j=0; j<4-hex.length(); j++) // Prepend zeros because unicode requires 4 digits
					ostr.append("0");
				ostr.append(hex.toLowerCase()); // standard unicode format.
				//ostr.append(hex.toLowerCase(Locale.ENGLISH));
			}
		}		 
		return (new String(ostr)); //Return the stringbuffer cast as a string.	 
	}
	
	public static boolean validationEmail(String email){
//		Pattern p=Pattern.compile("[a-zA-Z]*[0-9]*@[a-zA-Z]*.[a-zA-Z]*");
		Pattern p=Pattern.compile("^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$");
		Matcher m=p.matcher(email);
		boolean b=m.matches();
		return b;
	}
	
	public static String encoding(String value){
		try {
			return new String(value.getBytes("ISO8859_1"),"UTF-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return value;
	}
}
